#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
n8n工作流监控系统 - 核心监控脚本
功能：分析候选人聊天记录、计算业务指标、生成可视化报告
"""

import pymysql
import json
import re
from datetime import datetime, timedelta
from collections import defaultdict
from typing import Dict, List, Tuple
from decimal import Decimal
import os

# 导入配置
try:
    from config import DB_CONFIG, SENSITIVE_WORDS, SALARY_KEYWORDS, PHOTO_REQUEST_KEYWORDS, MONITOR_CONFIG, OUTPUT_CONFIG
except ImportError:
    print("[WARNING] 未找到config.py，使用默认配置")
    DB_CONFIG = {
        'host': 'localhost',
        'port': 3306,
        'user': 'root',
        'password': 'your_password',
        'database': 'your_database',
        'charset': 'utf8mb4'
    }
    SENSITIVE_WORDS = ['傻逼', 'SB', '草你妈']
    SALARY_KEYWORDS = ['工资', '薪资', '薪水', '月薪', '收入', '元', '钱']
    PHOTO_REQUEST_KEYWORDS = ['发照片', '要照片', '生活照', '自拍']
    MONITOR_CONFIG = {
        'reply_rate_days': 30,
        'content_analysis_days': 7,
        'workflow_error_days': 7,
        'daily_stats_days': 30,
    }
    OUTPUT_CONFIG = {
        'report_file': 'static/monitor_report.json',
        'verbose': True,
    }


class N8nMonitor:
    """n8n工作流监控器"""
    
    def __init__(self, db_config: Dict):
        """初始化监控器"""
        self.db_config = db_config
        self.conn = None
        self.cursor = None
    
    @staticmethod
    def convert_decimal(obj):
        """转换Decimal类型为Python原生类型，用于JSON序列化"""
        if isinstance(obj, Decimal):
            return float(obj)
        elif isinstance(obj, dict):
            return {k: N8nMonitor.convert_decimal(v) for k, v in obj.items()}
        elif isinstance(obj, list):
            return [N8nMonitor.convert_decimal(i) for i in obj]
        return obj
        
    def connect_db(self):
        """连接数据库"""
        try:
            self.conn = pymysql.connect(**self.db_config)
            self.cursor = self.conn.cursor(pymysql.cursors.DictCursor)
            print("[SUCCESS] 数据库连接成功")
            return True
        except Exception as e:
            print(f"[ERROR] 数据库连接失败: {e}")
            return False
    
    def close_db(self):
        """关闭数据库连接"""
        if self.cursor:
            self.cursor.close()
        if self.conn:
            self.conn.close()
    
    # ========================================
    # 核心业务指标分析
    # ========================================
    
    def analyze_reply_rate(self, days: int = 30) -> Dict:
        """
        分析回流率：统计发送消息后，候选人是否回复
        
        候选人分类：
        1. 主动候选人：第一条消息是AI发送的（AI主动打招呼）
        2. 被动候选人：第一条消息是候选人发送的（候选人主动联系AI）
        
        回流定义：无论是哪种候选人，只要回复了AI发送的消息，都算回流
        
        返回三种回流率：
        1. 总回流率：所有候选人的回流情况
        2. 主动候选人回流率：主动候选人的回流情况
        3. 被动候选人回流率：被动候选人的回流情况
        """
        print(f"\n[ANALYZE] 分析最近 {days} 天的回流率...")
        
        # 查询最近N天的所有候选人
        query = """
        SELECT DISTINCT c.id, c.boss_uid, c.name, c.status
        FROM candidates c
        WHERE c.updated_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
        """
        self.cursor.execute(query, (days,))
        candidates = self.cursor.fetchall()
        
        total_candidates = len(candidates)
        active_count = 0  # 主动候选人的数量（第一条消息是AI发送的）
        passive_count = 0  # 被动候选人的数量（第一条消息是候选人发送的）
        active_replied_count = 0  # 主动候选人中回流的数量
        passive_replied_count = 0  # 被动候选人中回流的数量
        total_replied_count = 0  # 总回流数量
        
        candidate_details = []
        
        for candidate in candidates:
            cid = candidate['id']
            
            # 获取该候选人的所有消息
            msg_query = """
            SELECT sender, content, created_at
            FROM messages
            WHERE candidate_id = %s
            ORDER BY created_at ASC
            """
            self.cursor.execute(msg_query, (cid,))
            messages = self.cursor.fetchall()
            
            if not messages:
                # 没有消息记录的候选人，归类为被动候选人且未回流
                passive_count += 1
                candidate_details.append({
                    'id': candidate['id'],
                    'name': candidate['name'],
                    'boss_uid': candidate['boss_uid'],
                    'status': candidate['status'],
                    'total_messages': 0,
                    'replied_back': False,
                    'is_active_candidate': False,
                    'chat_history': []
                })
                continue
            
            # 判断第一条消息的发送者，确定候选人类型
            first_message_sender = messages[0]['sender']
            is_active_candidate = (first_message_sender == '我')  # 第一条消息是AI发送的
            
            # 判断是否有AI发送的消息
            has_ai_message = any(msg['sender'] == '我' for msg in messages)
            
            # 判断候选人是否回复了AI的消息（回流判断）
            ai_sent = False
            candidate_replied_to_ai = False
            
            for msg in messages:
                if msg['sender'] == '我':
                    ai_sent = True
                elif ai_sent and msg['sender'] != '我':
                    candidate_replied_to_ai = True
                    break
            
            # 统计各类人数
            if is_active_candidate:
                active_count += 1
                if candidate_replied_to_ai:
                    active_replied_count += 1
                    total_replied_count += 1  # 主动候选人中回流的
            else:
                passive_count += 1
                if candidate_replied_to_ai:
                    passive_replied_count += 1
                    total_replied_count += 1  # 被动候选人中回流的
            
            # 格式化聊天记录，包含完整对话历史
            chat_messages = []
            for msg in messages:
                chat_messages.append({
                    'sender': msg['sender'],
                    'content': msg['content'],
                    'time': msg['created_at'].strftime('%Y-%m-%d %H:%M:%S') if msg['created_at'] and hasattr(msg['created_at'], 'strftime') else str(msg['created_at']) if msg['created_at'] else ''
                })
            
            # 添加所有有消息记录的候选人
            candidate_details.append({
                'id': candidate['id'],
                'name': candidate['name'],
                'boss_uid': candidate['boss_uid'],
                'status': candidate['status'],
                'total_messages': len(messages),
                'replied_back': candidate_replied_to_ai,
                'is_active_candidate': is_active_candidate,
                'chat_history': chat_messages
            })
        
        # 计算三种回流率
        total_reply_rate = (total_replied_count / total_candidates * 100) if total_candidates > 0 else 0
        active_reply_rate = (active_replied_count / active_count * 100) if active_count > 0 else 0
        passive_reply_rate = (passive_replied_count / passive_count * 100) if passive_count > 0 else 0
        
        result = {
            'total_candidates': total_candidates,
            'active_count': active_count,
            'passive_count': passive_count,
            'total_replied_count': total_replied_count,
            'active_replied_count': active_replied_count,
            'passive_replied_count': passive_replied_count,
            'total_reply_rate': round(total_reply_rate, 2),
            'active_reply_rate': round(active_reply_rate, 2),
            'passive_reply_rate': round(passive_reply_rate, 2),
            # 保持向后兼容
            'tracked_count': active_count,
            'untracked_count': passive_count,
            'tracked_replied_count': active_replied_count,
            'untracked_replied_count': passive_replied_count,
            'tracked_reply_rate': round(active_reply_rate, 2),
            'untracked_reply_rate': round(passive_reply_rate, 2),
            'reply_rate': round(active_reply_rate, 2),
            'replied_count': active_replied_count,
            'details': candidate_details
        }
        
        print(f"   总候选人数: {total_candidates}")
        print(f"   主动候选人数: {active_count}")
        print(f"   被动候选人数: {passive_count}")
        print(f"   总回流人数: {total_replied_count}")
        print(f"   主动回流人数: {active_replied_count}")
        print(f"   被动回流人数: {passive_replied_count}")
        print(f"   总回流率: {total_reply_rate:.2f}%")
        print(f"   主动回流率: {active_reply_rate:.2f}%")
        print(f"   被动回流率: {passive_reply_rate:.2f}%")
        
        return result
    
    def analyze_ai_replies(self, days: int = 7) -> Dict:
        """
        分析AI回复内容：检查是否包含敏感词、薪资信息
        """
        print(f"\n[ANALYZE] 分析最近 {days} 天的AI回复内容...")
        
        # 查询所有AI发送的消息
        query = """
        SELECT m.id, m.candidate_id, m.content, m.created_at, c.name as candidate_name
        FROM messages m
        JOIN candidates c ON m.candidate_id = c.id
        WHERE m.sender = '我' 
        AND m.created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
        ORDER BY m.created_at DESC
        """
        self.cursor.execute(query, (days,))
        ai_messages = self.cursor.fetchall()
        
        total_ai_messages = len(ai_messages)
        salary_info_count = 0
        sensitive_word_count = 0
        
        issues = []
        
        for msg in ai_messages:
            content = msg['content']
            
            # 检查是否包含薪资信息
            has_salary = self._check_salary_info(content)
            if has_salary:
                salary_info_count += 1
            
            # 检查敏感词
            detected_words = self._check_sensitive_words(content)
            if detected_words:
                sensitive_word_count += 1
                issues.append({
                    'type': 'sensitive_word',
                    'candidate_name': msg['candidate_name'],
                    'content': content[:100] + '...' if len(content) > 100 else content,
                    'detected_words': detected_words,
                    'created_at': msg['created_at'].strftime('%Y-%m-%d %H:%M:%S') if hasattr(msg['created_at'], 'strftime') else str(msg['created_at'])
                })
        
        result = {
            'total_ai_messages': total_ai_messages,
            'salary_info_count': salary_info_count,
            'salary_info_rate': round(salary_info_count / total_ai_messages * 100, 2) if total_ai_messages > 0 else 0,
            'sensitive_word_count': sensitive_word_count,
            'issues': issues
        }
        
        print(f"   总AI消息数: {total_ai_messages}")
        print(f"   包含薪资信息: {salary_info_count} ({result['salary_info_rate']:.2f}%)")
        print(f"   包含敏感词: {sensitive_word_count}")
        
        return result
    
    def analyze_photo_requests(self, days: int = 7) -> Dict:
        """
        分析索要照片信息：检查AI回复中是否包含索要照片的内容
        """
        print(f"\n[PHOTO] 分析最近 {days} 天的索要照片信息...")
        
        # 查询所有AI发送的消息
        query = """
        SELECT m.id, m.candidate_id, m.content, m.created_at, c.name as candidate_name
        FROM messages m
        JOIN candidates c ON m.candidate_id = c.id
        WHERE m.sender = '我' 
        AND m.created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
        ORDER BY m.created_at DESC
        """
        self.cursor.execute(query, (days,))
        ai_messages = self.cursor.fetchall()
        
        total_ai_messages = len(ai_messages)
        photo_request_count = 0
        
        issues = []
        
        for msg in ai_messages:
            content = msg['content']
            
            # 检查是否包含索要照片信息
            has_photo_request = self._check_photo_request(content)
            if has_photo_request:
                photo_request_count += 1
                issues.append({
                    'type': 'photo_request',
                    'candidate_name': msg['candidate_name'],
                    'content': content[:100] + '...' if len(content) > 100 else content,
                    'created_at': msg['created_at'].strftime('%Y-%m-%d %H:%M:%S') if hasattr(msg['created_at'], 'strftime') else str(msg['created_at']) if hasattr(msg['created_at'], 'strftime') else str(msg['created_at'])
                })
        
        result = {
            'total_ai_messages': total_ai_messages,
            'photo_request_count': photo_request_count,
            'photo_request_rate': round(photo_request_count / total_ai_messages * 100, 2) if total_ai_messages > 0 else 0,
            'issues': issues
        }
        
        print(f"   总AI消息数: {total_ai_messages}")
        print(f"   包含索要照片信息: {photo_request_count} ({result['photo_request_rate']:.2f}%)")
        
        return result
    
    def analyze_workflow_errors(self, days: int = 7) -> Dict:
        """
        分析工作流错误情况（从workflow_logs表读取）
        如果表为空或不存在，返回默认数据
        """
        print(f"\n[ANALYZE] 分析最近 {days} 天的工作流错误...")
        
        try:
            query = """
            SELECT 
                execution_status,
                COUNT(*) as count,
                AVG(execution_time_ms) as avg_time,
                MAX(execution_time_ms) as max_time
            FROM workflow_logs
            WHERE created_at >= DATE_SUB(NOW(), INTERVAL %s DAY)
            GROUP BY execution_status
            """
            self.cursor.execute(query, (days,))
            results = self.cursor.fetchall()
            
            stats = {
                'success': 0,
                'error': 0,
                'timeout': 0,
                'avg_time_ms': 0,
                'max_time_ms': 0
            }
            
            for row in results:
                status = row['execution_status']
                stats[status] = row['count']
                if status == 'success':
                    stats['avg_time_ms'] = int(row['avg_time'] or 0)
                    stats['max_time_ms'] = int(row['max_time'] or 0)
            
            total = stats['success'] + stats['error'] + stats['timeout']
            stats['total_executions'] = total
            stats['success_rate'] = round(stats['success'] / total * 100, 2) if total > 0 else 100
            
            print(f"   总执行次数: {total}")
            print(f"   成功: {stats['success']}")
            print(f"   错误: {stats['error']}")
            print(f"   超时: {stats['timeout']}")
            print(f"   成功率: {stats['success_rate']}%")
            
            return stats
            
        except Exception as e:
            print(f"   [WARNING] 无法读取workflow_logs表（可能表不存在）: {e}")
            return {
                'total_executions': 0,
                'success': 0,
                'error': 0,
                'timeout': 0,
                'success_rate': 100,
                'avg_time_ms': 0,
                'max_time_ms': 0,
                'note': '需要在n8n工作流中添加日志记录节点'
            }
    
    def get_daily_stats(self, days: int = 30) -> List[Dict]:
        """
        获取每日统计数据（用于图表展示）
        """
        print(f"\n[STATS] 获取最近 {days} 天的每日统计...")
        
        daily_data = []
        
        for i in range(days - 1, -1, -1):
            target_date = datetime.now() - timedelta(days=i)
            date_str = target_date.strftime('%Y-%m-%d')
            
            # 查询当天的消息数
            query = """
            SELECT 
                COUNT(*) as total_messages,
                SUM(CASE WHEN sender = '我' THEN 1 ELSE 0 END) as ai_messages,
                SUM(CASE WHEN sender != '我' THEN 1 ELSE 0 END) as candidate_messages,
                COUNT(DISTINCT candidate_id) as active_candidates
            FROM messages
            WHERE DATE(created_at) = %s
            """
            self.cursor.execute(query, (date_str,))
            result = self.cursor.fetchone()
            
            daily_data.append({
                'date': date_str,
                'total_messages': result['total_messages'] or 0,
                'ai_messages': result['ai_messages'] or 0,
                'candidate_messages': result['candidate_messages'] or 0,
                'active_candidates': result['active_candidates'] or 0
            })
        
        return daily_data
    
    def get_enhanced_statistics(self, days: int = 30) -> Dict:
        """
        获取增强的统计数据，包括趋势分析、准确性验证等
        """
        print(f"\n[ENHANCED] 获取增强统计数据...")
        
        # 获取每日统计数据
        daily_stats = self.get_daily_stats(days)
        
        # 计算趋势分析
        if len(daily_stats) >= 7:
            recent_7_days = daily_stats[-7:]
            previous_7_days = daily_stats[-14:-7] if len(daily_stats) >= 14 else daily_stats[:-7]
            
            # 计算平均消息数趋势
            recent_avg = sum(d['total_messages'] for d in recent_7_days) / len(recent_7_days)
            previous_avg = sum(d['total_messages'] for d in previous_7_days) / len(previous_7_days) if previous_7_days else recent_avg
            
            message_trend = "increasing" if recent_avg > previous_avg else "decreasing" if recent_avg < previous_avg else "stable"
            message_growth_rate = ((recent_avg - previous_avg) / previous_avg * 100) if previous_avg > 0 else 0
            
            # 计算活跃候选人数趋势
            recent_active_avg = sum(d['active_candidates'] for d in recent_7_days) / len(recent_7_days)
            previous_active_avg = sum(d['active_candidates'] for d in previous_7_days) / len(previous_7_days) if previous_7_days else recent_active_avg
            
            active_trend = "increasing" if recent_active_avg > previous_active_avg else "decreasing" if recent_active_avg < previous_active_avg else "stable"
            active_growth_rate = ((recent_active_avg - previous_active_avg) / previous_active_avg * 100) if previous_active_avg > 0 else 0
        else:
            message_trend = "insufficient_data"
            message_growth_rate = 0
            active_trend = "insufficient_data"
            active_growth_rate = 0
        
        # 计算总体统计
        total_messages = sum(d['total_messages'] for d in daily_stats)
        total_ai_messages = sum(d['ai_messages'] for d in daily_stats)
        total_candidate_messages = sum(d['candidate_messages'] for d in daily_stats)
        avg_daily_messages = total_messages / len(daily_stats) if daily_stats else 0
        avg_daily_active = sum(d['active_candidates'] for d in daily_stats) / len(daily_stats) if daily_stats else 0
        
        # 计算消息分布
        ai_message_ratio = (total_ai_messages / total_messages * 100) if total_messages > 0 else 0
        candidate_message_ratio = (total_candidate_messages / total_messages * 100) if total_messages > 0 else 0
        
        # 数据质量检查
        data_quality_score = self._calculate_data_quality_score(daily_stats)
        
        enhanced_stats = {
            'period_days': days,
            'total_messages': total_messages,
            'total_ai_messages': total_ai_messages,
            'total_candidate_messages': total_candidate_messages,
            'avg_daily_messages': round(avg_daily_messages, 2),
            'avg_daily_active_candidates': round(avg_daily_active, 2),
            'ai_message_ratio': round(ai_message_ratio, 2),
            'candidate_message_ratio': round(candidate_message_ratio, 2),
            'message_trend': message_trend,
            'message_growth_rate': round(message_growth_rate, 2),
            'active_trend': active_trend,
            'active_growth_rate': round(active_growth_rate, 2),
            'data_quality_score': data_quality_score,
            'daily_breakdown': daily_stats
        }
        
        print(f"   总消息数: {total_messages}")
        print(f"   AI消息占比: {ai_message_ratio:.2f}%")
        print(f"   消息趋势: {message_trend} ({message_growth_rate:+.2f}%)")
        print(f"   数据质量评分: {data_quality_score}/100")
        
        return enhanced_stats
    
    def _calculate_data_quality_score(self, daily_stats: List[Dict]) -> int:
        """
        计算数据质量评分（0-100）
        """
        if not daily_stats:
            return 0
        
        score = 100
        
        # 检查数据完整性
        for stat in daily_stats:
            # 检查必需字段
            required_fields = ['total_messages', 'ai_messages', 'candidate_messages', 'active_candidates']
            for field in required_fields:
                if field not in stat or stat[field] is None:
                    score -= 10
            
            # 检查数据一致性
            if stat.get('total_messages', 0) != stat.get('ai_messages', 0) + stat.get('candidate_messages', 0):
                score -= 5
            
            # 检查异常值
            if stat.get('total_messages', 0) < 0:
                score -= 15
            if stat.get('active_candidates', 0) < 0:
                score -= 10
        
        # 检查数据连续性
        zero_days = sum(1 for stat in daily_stats if stat.get('total_messages', 0) == 0)
        if zero_days > len(daily_stats) * 0.5:  # 超过50%的天数为0
            score -= 20
        
        return max(0, min(100, score))
    
    # ========================================
    # 辅助方法
    # ========================================
    
    def _check_salary_info(self, text: str) -> bool:
        """检查文本是否包含薪资信息"""
        text_lower = text.lower()
        return any(keyword in text or keyword in text_lower for keyword in SALARY_KEYWORDS)
    
    def _check_sensitive_words(self, text: str) -> List[str]:
        """检查文本是否包含敏感词，返回检测到的敏感词列表"""
        detected = []
        text_lower = text.lower()
        
        for word in SENSITIVE_WORDS:
            if word in text or word.lower() in text_lower:
                detected.append(word)
        
        return detected
    
    def _check_photo_request(self, text: str) -> bool:
        """检查文本是否包含索要照片信息"""
        text_lower = text.lower()
        return any(keyword in text or keyword in text_lower for keyword in PHOTO_REQUEST_KEYWORDS)
    
    def generate_detail_url(self, detail_type: str) -> str:
        """生成详情页URL"""
        return f"detail.html?type={detail_type}"
    
    def generate_access_url(self, port: int = 8000) -> str:
        """生成访问网址"""
        import socket
        try:
            # 获取本机IP地址
            hostname = socket.gethostname()
            local_ip = socket.gethostbyname(hostname)
            return f"http://{local_ip}:{port}/index.html"
        except:
            # 如果获取IP失败，使用localhost
            return f"http://localhost:{port}/index.html"
    
    def save_access_url(self, url_file: str = "access_url.txt"):
        """保存访问网址到文件"""
        url = self.generate_access_url()
        with open(url_file, 'w', encoding='utf-8') as f:
            f.write(f"监控系统访问地址：\n{url}\n\n")
            f.write(f"生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        print(f"[SUCCESS] 访问网址已保存到: {url_file}")
        print(f"[URL] 监控系统访问地址: {url}")
    
    def get_user_chat_records(self, candidate_id: int, limit: int = 100, message_type: str = None) -> Dict:
        """
        获取指定用户的聊天记录
        
        Args:
            candidate_id: 候选人ID
            limit: 限制返回消息数量
            message_type: 消息类型过滤 ('ai' 或 'candidate')
        
        Returns:
            包含候选人信息和聊天记录的字典
        """
        try:
            with self.conn.cursor(pymysql.cursors.DictCursor) as cursor:
                # 获取候选人信息
                candidate_query = """
                SELECT id, name, phone, email, created_at
                FROM candidates 
                WHERE id = %s
                """
                cursor.execute(candidate_query, (candidate_id,))
                candidate_result = cursor.fetchone()
                
                if not candidate_result:
                    return {
                        'candidate': None,
                        'messages': [],
                        'total_messages': 0,
                        'ai_messages': 0,
                        'candidate_messages': 0,
                        'error': '用户不存在'
                    }
                
                # 构建消息查询
                message_query = """
                SELECT id, sender, content, created_at
                FROM messages 
                WHERE candidate_id = %s
                """
                params = [candidate_id]
                
                # 添加消息类型过滤
                if message_type == 'ai':
                    message_query += " AND sender = '我'"
                elif message_type == 'candidate':
                    message_query += " AND sender != '我'"
                
                message_query += " ORDER BY created_at ASC LIMIT %s"
                params.append(limit)
                
                cursor.execute(message_query, params)
                messages = cursor.fetchall()
                
                # 处理时间格式
                processed_messages = []
                ai_count = 0
                candidate_count = 0
                
                for msg in messages:
                    processed_msg = {
                        'id': msg['id'],
                        'sender': msg['sender'],
                        'content': msg['content'],
                        'created_at': msg['created_at'].strftime('%Y-%m-%d %H:%M:%S') if hasattr(msg['created_at'], 'strftime') else str(msg['created_at'])
                    }
                    processed_messages.append(processed_msg)
                    
                    # 统计消息类型
                    if msg['sender'] == '我':
                        ai_count += 1
                    else:
                        candidate_count += 1
                
                return {
                    'candidate': candidate_result,
                    'messages': processed_messages,
                    'total_messages': len(processed_messages),
                    'ai_messages': ai_count,
                    'candidate_messages': candidate_count
                }
                
        except Exception as e:
            return {
                'candidate': None,
                'messages': [],
                'total_messages': 0,
                'ai_messages': 0,
                'candidate_messages': 0,
                'error': str(e)
            }
    
    def generate_user_chat_url(self, candidate_id: int) -> str:
        """生成用户聊天记录URL"""
        return f"user_chat.html?candidate_id={candidate_id}"
    
    # ========================================
    # 主执行方法
    # ========================================
    
    def generate_report(self, output_file: str = None):
        """
        生成完整的监控报告
        """
        if output_file is None:
            output_file = OUTPUT_CONFIG.get('report_file', 'static/monitor_report.json')
        
        print("=" * 60)
        print("[START] 开始生成n8n工作流监控报告")
        print("=" * 60)
        
        if not self.connect_db():
            return False
        
        try:
            # 1. 回流率分析
            reply_stats = self.analyze_reply_rate(days=MONITOR_CONFIG['reply_rate_days'])
            
            # 2. AI回复内容分析
            content_stats = self.analyze_ai_replies(days=MONITOR_CONFIG['content_analysis_days'])
            
            # 3. 索要照片信息分析
            photo_stats = self.analyze_photo_requests(days=MONITOR_CONFIG['content_analysis_days'])
            
            # 4. 工作流错误分析
            error_stats = self.analyze_workflow_errors(days=MONITOR_CONFIG['workflow_error_days'])
            
            # 5. 每日统计数据
            daily_stats = self.get_daily_stats(days=MONITOR_CONFIG['daily_stats_days'])
            
            # 6. 增强统计数据
            enhanced_stats = self.get_enhanced_statistics(days=MONITOR_CONFIG['daily_stats_days'])
            
            # 汇总报告
            report = {
                'generated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'summary': {
                    'total_candidates': reply_stats['total_candidates'],
                    'active_candidates': reply_stats['active_count'],
                    'passive_candidates': reply_stats['passive_count'],
                    'total_replied_candidates': reply_stats['total_replied_count'],
                    'active_replied_candidates': reply_stats['active_replied_count'],
                    'passive_replied_candidates': reply_stats['passive_replied_count'],
                    'total_reply_rate': reply_stats['total_reply_rate'],
                    'active_reply_rate': reply_stats['active_reply_rate'],
                    'passive_reply_rate': reply_stats['passive_reply_rate'],
                    # 保持向后兼容
                    'tracked_candidates': reply_stats['tracked_count'],
                    'untracked_candidates': reply_stats['untracked_count'],
                    'tracked_replied_candidates': reply_stats['tracked_replied_count'],
                    'untracked_replied_candidates': reply_stats['untracked_replied_count'],
                    'tracked_reply_rate': reply_stats['tracked_reply_rate'],
                    'untracked_reply_rate': reply_stats['untracked_reply_rate'],
                    'replied_candidates': reply_stats['replied_count'],
                    'reply_rate': reply_stats['reply_rate'],
                    'total_ai_messages': content_stats['total_ai_messages'],
                    'salary_mentions': content_stats['salary_info_count'],
                    'sensitive_issues': content_stats['sensitive_word_count'],
                    'photo_requests': photo_stats['photo_request_count'],
                    'workflow_errors': error_stats['error'],
                    'workflow_success_rate': error_stats['success_rate']
                },
                'reply_rate_details': reply_stats,
                'content_analysis': content_stats,
                'photo_request_analysis': photo_stats,
                'workflow_performance': error_stats,
                'daily_statistics': daily_stats,
                'enhanced_statistics': enhanced_stats
            }
            
            # 转换Decimal类型并保存为JSON文件
            report = self.convert_decimal(report)
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(report, f, ensure_ascii=False, indent=2)
            
            print("\n" + "=" * 60)
            print(f"[SUCCESS] 报告生成成功！已保存到: {output_file}")
            print("=" * 60)
            print(f"\n[STATS] 核心指标概览:")
            print(f"   - 总回流率: {reply_stats['total_reply_rate']:.2f}% ({reply_stats['total_replied_count']}/{reply_stats['total_candidates']})")
            print(f"   - 主动回流率: {reply_stats['active_reply_rate']:.2f}% ({reply_stats['active_replied_count']}/{reply_stats['active_count']})")
            print(f"   - 被动回流率: {reply_stats['passive_reply_rate']:.2f}% ({reply_stats['passive_replied_count']}/{reply_stats['passive_count']})")
            print(f"   - 薪资信息提及: {content_stats['salary_info_count']} 次")
            print(f"   - 敏感词检测: {content_stats['sensitive_word_count']} 次")
            print(f"   - 索要照片信息: {photo_stats['photo_request_count']} 次")
            print(f"   - 工作流成功率: {error_stats['success_rate']}%")
            
            return report
            
        except Exception as e:
            print(f"\n[ERROR] 生成报告时出错: {e}")
            import traceback
            traceback.print_exc()
            return False
        finally:
            self.close_db()


# ========================================
# 主程序入口
# ========================================

def main():
    """主函数"""
    print("\n" + "=" * 60)
    print("  n8n工作流监控系统 v1.0")
    print("=" * 60)
    
    # 创建监控器实例
    monitor = N8nMonitor(DB_CONFIG)
    
    # 生成报告
    success = monitor.generate_report()
    
    if success:
        # 生成并保存访问网址
        monitor.save_access_url()
        print("\n[TIP] 提示: 请在浏览器中打开 index.html 查看可视化报告\n")
    else:
        print("\n[ERROR] 报告生成失败，请检查数据库配置和连接\n")


if __name__ == '__main__':
    main()

